home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / tex / concat10.zip / CONCAT10.ASM < prev    next >
Assembly Source File  |  1989-05-02  |  12KB  |  506 lines

  1.     TITLE    Concat
  2.  
  3. ;Input:
  4. ;    Read in multiple files (as named on the DOS cmd line).
  5. ;    Wildcards and full pathing are supported.
  6. ;
  7. ;Output:
  8. ;    To StdOut (e.g., via redirection at the DOS command line).
  9. ;    (No ^Z is appended to the output.)
  10. ;
  11. ;End of File:
  12. ;    Assumes the first ^Z in each file is EOF (and the rest is garbage),
  13. ;    so will discard everything after that first ^Z.
  14. ;Notes:
  15. ;    Makes no attempt to add terminating CR/LF to each file
  16. ;    or any other such cleanup.
  17.  
  18. ;Released to the public domain
  19. ;David Kirschbaum
  20. ;Toad Hall
  21. ;kirsch@braggvax.ARPA
  22.  
  23. CR    equ    0DH
  24. LF    equ    0AH
  25. CTRLZ    equ    1AH        ;Ctrl-Z
  26.  
  27. STDOUT    equ    1        ;DOS StdOut
  28. STDERR    equ    2        ;DOS StdErr (screen)
  29.  
  30. DTA_TYPE    struc
  31. reserved    db    21 DUP(?)    ;Used by DOS for find next
  32. attrib        db    ?        ;file attribute
  33. time        dw    ?        ;file time stamp
  34. date        dw    ?        ;file date stamp
  35. filesize    dw    ?,?        ;file size in bytes (long integer)
  36. filename    db    13 DUP(?)    ;AsciiZ filename string
  37. DTA_TYPE    ends
  38.  
  39. CSEG    segment    public    'CODE'
  40.     assume CS:CSEG,DS:CSEG
  41.  
  42.     org    80H
  43. dta    label    DTA_TYPE
  44. nchar    db    ?            ;for Args
  45. params    db    ?
  46.  
  47. ;    org    fcb_dta + 26        ;dta filesize
  48. ;filesize dw    ?,?
  49. ;
  50. ;    org    dta + 30        ;DTA.filename
  51. ;dtaname    db    ?            ;for wildcard expansion
  52.  
  53.     org    100H            ;yep, a .COM file
  54.  
  55. Concat    proc    near
  56.     jmp    Start            ;skip over data
  57.  
  58. usagemsg db    'CONCAT - Concatenate text files to StdOut',CR,LF
  59.     db    'Usage:  CONCAT [d:\]file1.txt file2.txt >output.txt',CR,LF
  60.     db    'Input:  Wildcards and full pathing permitted.',CR,LF
  61.     db    'Output: DOS Standard Output (redirectable).',CR,LF
  62.     db    'David Kirschbaum, Toad Hall, v1.0'
  63. crlf        db    CR,LF
  64. USAGEMSGLEN    equ    $ - usagemsg
  65. CRLFLEN        equ    $ - crlf
  66.  
  67. notfoundmsg    db    ' not found',CR,LF
  68. NOTFOUNDLEN    equ    $ - notfoundmsg    ;msg length
  69.  
  70. openerrmsg    db    ' File open error',CR,LF
  71. OPENERRLEN    equ    $ - openerrmsg
  72.  
  73. readerrmsg    db    ' File read error',CR,LF
  74. READERRLEN    equ    $ - readerrmsg
  75.  
  76. writerrmsg    db    ' File write error',CR,LF
  77. WRITERRLEN    equ    $ - writerrmsg
  78.  
  79. zerofilemsg    db    ' Empty file, skipped',CR,LF
  80. ZEROFILELEN    equ    $ - zerofilemsg
  81.  
  82. handle    dw    0            ;input file handle
  83.  
  84. Concat    endp
  85.  
  86.  
  87. ;Returns position of char in string
  88. ;DI -> string start or end
  89. ;AL =  char to seek
  90. ;Returns psn in CX
  91. ;It'll work in reverse also if you enter with DI -> string end
  92. ;and STD instead of CLD
  93.  
  94. Find_Char    proc    near
  95.     mov    cx,0FFFFH        ;max scan
  96.     repne    scasb
  97.     not    cx            ;CX=char psn
  98.     ret
  99. Find_Char    endp
  100.  
  101.  
  102. ;Display an AsciiZ string to StdErr
  103. ;Enters with SI -> AsciiZ string
  104. ;Destroys AX,DI
  105. ;Returns CX = string length, DX, SI -> AsciiZ string
  106.  
  107. Pr_AsciiZ    proc    near
  108.     xor    al,al            ;find terminating 0
  109.     mov    di,si            ;from string start
  110.     cld                ;go forward
  111.     call    Find_Char        ;CX = psn of 0, SI unchanged
  112.     dec    cx            ;- 1 for actual length
  113.     mov    dx,si            ;string start
  114.     mov    bx,STDERR        ;output to StdErr
  115.     mov    ah,40H            ;write to file/device
  116.     int    21H
  117.     ret
  118.  
  119. Pr_AsciiZ    endp
  120.  
  121.  
  122. ;Separate a drive:\path from an arg filename.
  123. ;SI -> arg (an AsciiZ string)
  124. ;Pointer pathend   -> beyond last char in path (filename[0] if none)
  125.  
  126. Split_Path    proc    near
  127.  
  128.     mov    di,si            ;from string start
  129.     xor    al,al            ;find AsciiZ arg end
  130.     cld                ;go forward
  131.     call    Find_Char        ;CX=psn of 0, DI -> beyond 0
  132.     dec    di            ;DI -> AsciiZ 0
  133.     dec    di            ;DI -> last char in filename
  134.  
  135.     mov    al,'\'            ;scan for subdirectories
  136.     std                ;backwards towards start
  137.     repne    scasb            ;CX has filename length
  138.     cld                ;insure forward again
  139.     or    cx,cx            ;any path?
  140.     jnz    Got_Path        ;yep
  141.  
  142. ;No '\',how about ':'?
  143.  
  144.     xor    cx,cx            ;assume no path, no move
  145.     mov    di,si            ;string start
  146.     cmp    byte ptr 1[di],':'    ;divider should be after drive char
  147.     jnz    No_Path            ;nope, DI -> filename's first char
  148.  
  149. ;In either case, DI should be pointing to the char
  150. ;BEFORE the path or drive separator.
  151.  
  152. Got_Path:
  153.     add    di,2            ;bump beyond '\' or ':'
  154.     mov    cx,di            ;path\filename end
  155.     sub    cx,si            ;- path end = bytes to move
  156. No_Path:
  157.     mov    di,offset path        ;move into path
  158.     jcxz    No_Path_Move
  159.      rep    movsb            ;copy args path into buffer
  160. No_Path_Move:
  161.     mov    word ptr pathptr,di    ;pathptr -> char beyond args path
  162.                     ;where we'll move the filename
  163. Split_Path    endp
  164.  
  165.  
  166.  
  167. ;Move our expanded filename after our arg path.
  168.  
  169. Add_Path    proc    near
  170.     mov    si,offset dta.filename        ;expanded filename
  171.     mov    di,si                ;Find_Char wants it in DI
  172.     xor    al,al                ;get AsciiZ name length
  173.     cld                    ;forward
  174.     call    Find_Char            ;CX = char psn, SI unchanged
  175.     mov    di,word ptr pathptr        ;-> arg path + 1 (or start)
  176.     rep    movsb                ;move in the name
  177.                         ;(include the AsciiZ 0)
  178.     mov    si,offset path            ;-> path start
  179.     ret
  180. Add_Path    endp
  181.  
  182.  
  183. ;Displays expanded filename
  184. ;Copies the wildcard file to StdOut
  185. ;Enter with SI -> expanded filename
  186. ;On return:
  187. ;  handle = file handle (or 0 if never opened)
  188. ;  CF set = error
  189. ;  DX=CR/LF or error msg (if error)
  190. ;  CX = msg length
  191.  
  192. Copy_File    proc    near
  193.     mov    handle,0        ;insure file handle is cleared
  194.  
  195.     call    Add_Path        ;add arg path to expanded filename
  196.                     ;(we could be doing a Find Next)
  197.                     ;returns SI, DX -> path:\name
  198.     call    Pr_AsciiZ        ;display AsciiZ name
  199.                     ;DX -> AsciiZ path:\name
  200.  
  201.     mov    ax,3D00H        ;open for read only
  202.     int    21H
  203.     jb    Open_Err        ;failed
  204.  
  205.     mov    handle,ax        ;save the handle
  206.  
  207.     mov    si,offset dta.filesize    ;DTA filesize long integer
  208.     lodsw                ;get filesize.lo
  209.     or    ax,[si]            ;test filesize.hi
  210.     jz    Zero_File        ;empty file, forget it
  211.  
  212. ReadLup:
  213.     mov    dx,offset readbuff    ;file read buffer
  214.     mov    cx,READBUFFSIZE        ;bytes to read
  215.     mov    bx,handle        ;file handle
  216.     mov    ah,3FH            ;read from file/device
  217.     int    21H
  218.     jb    Read_Err        ;read failed
  219.  
  220.     mov    cx,ax            ;bytes read
  221.     jcxz    File_Eof1        ;nothing read, it's EOF
  222.  
  223.     mov    bx,ax            ;remember bytes read
  224.     mov    di,dx            ;DI -> read buffer
  225.     mov    al,CTRLZ        ;scan for terminating Ctrl Z
  226.     repne    scasb
  227.     jz    File_EOF        ;it's logical EOF
  228.  
  229.     mov    cx,bx            ;restore nr bytes read
  230.     mov    bx,STDOUT        ;output to StdOut
  231.     mov    ah,40H            ;write to file/device
  232.     int    21H
  233.     jnb    ReadLup            ;wrote ok, keep going
  234.  
  235. Write_Err:
  236.     mov    dx,offset writerrmsg    ;' File write error'
  237.     mov    cx,WRITERRLEN
  238.     ret                ;CF set
  239.  
  240. Zero_File:
  241.     mov    dx,offset zerofilemsg    ;' Zero file size .. skipped'
  242.     mov    cx,ZEROFILELEN
  243.     ret                ;CF clear
  244.     
  245. Read_Err:
  246.     mov    dx,offset readerrmsg    ;' File read error'
  247.     mov    cx,READERRLEN
  248.     ret                ;CF set
  249.  
  250. File_Eof:
  251.     inc    cx            ;adjust for that Ctrl Z
  252.     sub    bx,cx            ; bytes read - Ctrl Z psn
  253.     mov    cx,bx            ;= bytes to write
  254.     mov    bx,STDOUT        ;output to StdOut
  255.     mov    ah,40H            ;write to file/device
  256.     int    21H
  257.     jb    Write_Err        ;final write failed
  258.  
  259. File_Eof1:
  260.     mov    dx,offset crlf        ;new line after filename
  261.     mov    cx,CRLFLEN
  262.     ret                ;CF should be clear
  263.  
  264. Open_Err:
  265.     mov    dx,offset openerrmsg    ;'File open error'
  266.     mov    cx,OPENERRLEN
  267.     ret                ;CF set
  268.  
  269. Copy_File    endp
  270.  
  271.  
  272. ;Do a wildcard copy.
  273. ;SI -> AsciiZ filename
  274.  
  275. OutPut    proc    near
  276.  
  277.     mov    dx,si            ;DX = AsciiZ filename ptr
  278.     xor    cx,cx            ;no special attributes
  279.     mov    ah,4EH            ;find first
  280.     int    21H
  281.     or    ax,ax            ;find anything?
  282.     jz    Found_First        ;yep
  283.  
  284.      call    Pr_AsciiZ        ;display filename (still in SI)
  285.      mov    dx,offset notfoundmsg    ;' not found'
  286.      mov    cx,NOTFOUNDLEN        ;msg length
  287.      stc                ;CF set to exit
  288.      jmp    short Not_Found        ;display error msg, return
  289.  
  290. ;Remember, a Find First or Find Next will give us an expanded filename
  291. ;(in the DTA) but will NOT give us a path!
  292. ;We have to process the arg (SI still points to it) and split off
  293. ;the path from the filename.
  294.  
  295. Found_First:
  296.     call    Split_Path        ;separate arg path from arg
  297.                     ;arg filename (for Find First only).
  298.                     ;fall thru to...
  299. Find_Next:                ;our wildcard loop
  300.     call    Copy_File        ;open, copy the file
  301.  
  302. ;On return:
  303. ;  handle = file handle (or 0 if never opened)
  304. ;  CF set = error
  305. ;  DX=CR/LF or error msg (if error)
  306. ;  CX = msg length
  307.  
  308. Not_Found:
  309.     pushf                ;save copy flags
  310.     mov    bx,STDERR        ;Std Err handle
  311.     mov    ah,40H            ;write to file/device
  312.     int    21H
  313.  
  314.     mov    bx,handle        ;restore input file handle
  315.     or    bx,bx            ;ever opened?
  316.     jz    No_Handle        ;nope
  317.      mov    ah,3EH            ;close input file
  318.      int    21H
  319. No_Handle:
  320.  
  321.     popf                ;restore copy flags
  322.     jb    OutPutX            ;some sort of error
  323.  
  324. ;Now for the Find Next
  325.     mov    ah,4FH            ;continue file search
  326.     int    21H
  327.     cmp    al,18            ;no more files to be found?
  328.     jnz    Find_Next        ;nope, found one, continue
  329. Out